package main

import (
	"bufio"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"net"
	"os"
	"strings"
)

const (
	maxDataSize2 = 1024 * 1024 // 与服务端一致
	headerSize2  = 4           // 长度前缀头大小
)

func main() {
	conn, err := net.Dial("tcp", "127.0.0.1:20000")
	if err != nil {
		fmt.Println("连接失败:", err)
		return
	}
	defer conn.Close()
	fmt.Println("已连接到服务器 (使用长度前缀协议)")

	// 创建读取器和写入器
	reader := bufio.NewReader(conn)
	input := bufio.NewReader(os.Stdin)

	for {
		// 1. 读取用户输入
		fmt.Print("请输入内容> ")
		res, _ := input.ReadString('\n')
		res = strings.TrimSpace(res)

		// 2. 退出检查
		if res == "quit()" {
			fmt.Println("断开连接...")
			return
		}

		// 3. 发送消息 (带长度前缀)
		if err := sendMessage(conn, []byte(res)); err != nil {
			fmt.Println("发送失败:", err)
			continue
		}

		// 4. 接收响应 (带长度前缀)
		response, err := readMessage(reader)
		if err != nil {
			if errors.Is(err, io.EOF) {
				fmt.Println("服务器关闭连接")
				return
			}
			fmt.Println("接收失败:", err)
			continue
		}

		// 5. 显示响应 (限制显示长度)
		displayLen := 50
		if len(response) < displayLen {
			fmt.Printf("服务器响应<< %s\n", string(response))
		} else {
			fmt.Printf("服务器响应<< %s... [共%d字节]\n",
				string(response[:displayLen]), len(response))
		}
	}
}

// 发送带长度前缀的消息
func sendMessage(conn net.Conn, data []byte) error {
	// 1. 创建长度头 (uint32大端序)
	header := make([]byte, headerSize2)
	binary.BigEndian.PutUint32(header, uint32(len(data)))

	// 2. 组合头和消息
	fullMsg := append(header, data...)

	// 3. 发送完整数据包
	_, err := conn.Write(fullMsg)
	return err
}

// 读取带长度前缀的消息
func readMessage(reader *bufio.Reader) ([]byte, error) {
	// 1. 读取消息头
	header := make([]byte, headerSize2)
	if _, err := io.ReadFull(reader, header); err != nil {
		return nil, err
	}

	// 2. 解析数据长度
	dataSize := binary.BigEndian.Uint32(header)

	// 3. 校验长度
	if dataSize > maxDataSize2 {
		return nil, fmt.Errorf("数据大小超出限制: %d > %d", dataSize, maxDataSize2)
	}

	// 4. 读取消息体
	data := make([]byte, dataSize)
	if _, err := io.ReadFull(reader, data); err != nil {
		return nil, err
	}

	return data, nil
}
